package com.ruoyi.controller;

import com.fasterxml.jackson.databind.ObjectMapper;
import com.ruoyi.common.PageResult;
import com.ruoyi.common.Result;
import com.ruoyi.common.constant.Constants;
import com.ruoyi.common.utils.SecurityUtils;
import com.ruoyi.domain.dto.FileDTO;
import com.ruoyi.domain.pojo.FilePO;
import com.ruoyi.service.FileService;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.http.HttpStatus;
import org.springframework.http.MediaType;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.multipart.MultipartFile;

import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.net.URLEncoder;
import java.nio.charset.StandardCharsets;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.time.LocalDateTime;
import java.time.OffsetDateTime;
import java.time.format.DateTimeFormatter;
import java.time.format.DateTimeFormatterBuilder;
import java.util.*;

/**
 * @Classname FileController
 * @Description 文件管理控制器
 * @Date 2025/3/19 13:49
 * @Created by xxx
 */
@RestController
@Slf4j
@RequiredArgsConstructor
@Api(tags = "文件管理")
@RequestMapping("/api/v1/files")
public class FileController {

    private final FileService fileService;
    private static final Map<String, String> MONTH_MAP = new HashMap<>();
    static {
        MONTH_MAP.put("jan", "01");
        MONTH_MAP.put("feb", "02");
        MONTH_MAP.put("mar", "03");
        MONTH_MAP.put("apr", "04");
        MONTH_MAP.put("may", "05");
        MONTH_MAP.put("jun", "06");
        MONTH_MAP.put("jul", "07");
        MONTH_MAP.put("aug", "08");
        MONTH_MAP.put("sep", "09");
        MONTH_MAP.put("oct", "10");
        MONTH_MAP.put("nov", "11");
        MONTH_MAP.put("dec", "12");
    }

    /**
     * 直接截断字符串生成日期（要求输入格式严格固定）
     * @param dateStr 如 "Fri Apr 11 2025 09:42:40 GMT+0800 (GMT+08:00)"
     * @return "2025-04-11"
     * @throws IllegalArgumentException 如果输入格式不匹配
     */
    public static String truncateToYmd(String dateStr) {
        // 按空格分割字符串（假设格式严格固定）
        log.info("日期字符串: {}", dateStr);
        String[] parts = dateStr.split(" ");
        log.info("日期分割: {}", Arrays.toString(parts));

        // 提取关键字段（假设顺序为：星期 月 日 年 ...）
        String monthAbbr = parts[1].toLowerCase(); // 月份转小写
        String day = parts[2];
        String year = parts[3];

        // 转换月份
        String month = MONTH_MAP.get(monthAbbr);
        if (month == null) {
            throw new IllegalArgumentException("非法月份缩写: " + parts[1]);
        }

        // 补零日期（如 "5" → "05"）
        if (day.length() == 1) {
            day = "0" + day;
        }

        return String.format("%s-%s-%s", year, month, day);
    }

    @ApiOperation(value = "文件上传", notes = "文件上传")
    @PostMapping(value = "/upload", consumes = MediaType.MULTIPART_FORM_DATA_VALUE)
    public Result upload(@RequestParam("title") String title,
                         @RequestParam("type") Integer type,
                         @RequestParam("file") MultipartFile file,
                         @RequestParam("startTime") String startTime,
                         @RequestParam("endTime") String endTime,
                         @RequestParam("meetingName") String meetingName,
                         @RequestParam("meetingPlace") String meetingPlace,
                         @RequestParam("templateId") Integer templateId,
                         @RequestParam("collect") Integer collect) {
        Long userId = SecurityUtils.getUserId();
        if (userId == null) {
            return Result.error("请先登录");
        }
        log.info("会议时间{}", startTime);
        FileDTO fileDTO = FileDTO.builder()
                .title(title)
                .type(type)
                .file(file)
                .createBy(userId)
                .createTime(LocalDateTime.now())
                .startTime(startTime)
                .endTime(endTime)
                .meetingName(meetingName)
                .meetingPlace(meetingPlace)
                .templateId(templateId)
                .collect(collect)
                .build();
        if (!Objects.equals(startTime, "") && startTime != null) {
            String dates = truncateToYmd(startTime);
            log.info("日期格式化: {}", dates);
            fileDTO.setStartTime(dates);
        }
        log.info("文件上传: fileDTO: {}", fileDTO);
        boolean result = fileService.upload(fileDTO);
        if (result) {
            return Result.success();
        } else {
            return Result.error("文件不支持");
        }
    }

    @ApiOperation(value = "文件分页条件查询")
    @GetMapping(value = "/list")
    public Result list(FileDTO fileDTO) {
        Long userId = SecurityUtils.getUserId();
        if (userId == null) {
            return Result.success();
        }
        log.info("文件分页条件查询: fileDTO: {}", fileDTO);
        fileDTO.setCreateBy(userId);
        PageResult pageResult = fileService.list(fileDTO);
        return Result.success(pageResult);
    }

    @ApiOperation(value = "文件收藏/取消收藏")
    @PostMapping(value = "/collections")
    public Result collections(@RequestParam("id") Integer id) {
        Long userId = SecurityUtils.getUserId();
        if (userId == null) {
            return Result.error("请先登录");
        }
        log.info("文件收藏/取消收藏: id: {}, userId: {}", id, userId);
        boolean result = fileService.collections(id, userId);
        if (result) return Result.success();
        else return Result.error("收藏失败");
    }

    @ApiOperation(value = "文件删除/还原")
    @PostMapping(value = "/delete")
    public Result delete(@RequestParam("id") Integer id) {
        Long userId = SecurityUtils.getUserId();
        if (userId == null) {
            return Result.error("请先登录");
        }
        log.info("文件删除/还原: id: {}, userId: {}", id, userId);
        boolean result = fileService.delete(id, userId);
        if (result) return Result.success();
        else return Result.error("删除失败");
    }

    @ApiOperation(value = "彻底删除文件")
    @DeleteMapping("/delete/{id}")
    public Result realDelete(@PathVariable("id") Integer id) {
        Long userId = SecurityUtils.getUserId();
        if (userId == null) {
            return Result.error("请先登录");
        }
        log.info("彻底删除文件: id: {}, userId: {}", id, userId);
        boolean result = fileService.readDelete(id, userId);
        if (result) return Result.success();
        else return Result.error("删除失败");
    }

    @ApiOperation(value = "回收站清空")
    @DeleteMapping("/delete/clean")
    public Result clean() {
        Long userId = SecurityUtils.getUserId();
        if (userId == null) {
            return Result.error("请先登录");
        }
        log.info("回收站清空: userId: {}", userId);
        boolean result = fileService.clean(userId);
        if (result) return Result.success();
        else return Result.error("清空失败");
    }

    @ApiOperation(value = "文件下载")
    @PostMapping(value = "/download")
    public void download(@RequestParam("id") Integer id, @RequestParam("category") Integer category, HttpServletResponse response) {
        Long userId = SecurityUtils.getUserId();
        if (userId == null) {
            return;
        }
        log.info("文件下载: id: {}, category: {}", id, category);
        FilePO filePO = fileService.download(id, userId);
        response.setContentType("application/octet-stream");
        response.setStatus(HttpStatus.OK.value());
        Path filePath = null;
        String fileName = null;
        try {
            if (category == 0) {
                filePath = Paths.get(filePO.getFilePath());
                fileName = String.valueOf(filePath.getFileName());
                fileName = filePO.getTitle() + fileName.substring(fileName.lastIndexOf("."));
            } else if (category == 1) {
                if (filePO.getType() == Constants.TEXT) {
                    sendErrorResponse(response, "文本文件没有转写文件");
                    return;
                }
                filePath = Paths.get(filePO.getTransPath());
                fileName = String.valueOf(filePath.getFileName());
                fileName = filePO.getTitle() + fileName.substring(fileName.lastIndexOf("."));
            } else if (category == 2) {
                filePath = Paths.get(filePO.getMinutesPath());
                fileName = String.valueOf(filePath.getFileName());
                fileName = filePO.getTitle() + fileName.substring(fileName.lastIndexOf("."));
            } else {
                sendErrorResponse(response, "参数错误");
            }
            // 检查文件是否存在
            if (filePath != null && !Files.exists(filePath)) {
                sendErrorResponse(response, "文件不存在");
                return;
            }
            log.info("filePath: {}, fileName: {}", filePath, fileName);
            response.setContentType(MediaType.APPLICATION_OCTET_STREAM_VALUE);
            String encodedFileName = URLEncoder.encode(fileName, StandardCharsets.UTF_8.name()).replaceAll("\\+", "%20");
            response.setHeader("Content-Disposition", "attachment; filename=\"" + encodedFileName + "\"");
            if (filePath != null) {
                Files.copy(filePath, response.getOutputStream());
            }
            response.flushBuffer();
        } catch (IOException e) {
            sendErrorResponse(response, "文件读取失败");
        }

    }

    private void sendErrorResponse(HttpServletResponse response, String message) {
        int statusCode = HttpStatus.BAD_REQUEST.value();
        try {
            // 设置字符编码和内容类型
            response.setCharacterEncoding(StandardCharsets.UTF_8.name());
            response.setContentType(MediaType.APPLICATION_JSON_VALUE + ";charset=" + StandardCharsets.UTF_8.name());
            response.setStatus(statusCode);

            // 使用OutputStream替代Writer确保编码控制
            Result error = Result.error(message);
            String json = new ObjectMapper().writeValueAsString(error);
            response.getOutputStream().write(json.getBytes(StandardCharsets.UTF_8));
        } catch (IOException ex) {
            log.error("错误响应发送失败: {}", ex.getMessage());
            response.setStatus(HttpStatus.INTERNAL_SERVER_ERROR.value());
            try {
                response.flushBuffer();
            } catch (IOException e) {
                log.error("响应缓冲区刷新失败: {}", e.getMessage());
            }
        }
    }

    @ApiOperation(value = "文件详情")
    @GetMapping(value = "/detail")
    public Result getDetail(@RequestParam("id") Integer id) {
        Long userId = SecurityUtils.getUserId();
        if (userId == null) {
            return Result.error("请先登录");
        }
        log.info("文件详情: id: {}, userId: {}", id, userId);
        return fileService.getDetail(id, userId);
    }

    @ApiOperation(value = "纪要文件保存")
    @PostMapping(value = "/save")
    public Result save(@RequestBody FileDTO fileDTO) {
        Long userId = SecurityUtils.getUserId();
        if (userId == null) {
            return Result.error("请先登录");
        }
        String minutes = fileDTO.getMinutes();
        Integer id = fileDTO.getId();
        log.info("纪要文件保存: id: {}, userId: {}, minutes: {}", id, userId, minutes);
        return fileService.save(id, userId, minutes);
    }

    @ApiOperation(value = "文件重做")
    @PostMapping(value = "/redo")
    public Result redo(@RequestParam("id") Integer id) {
        Long userId = SecurityUtils.getUserId();
        if (userId == null) {
            return Result.error("请先登录");
        }
        log.info("文件重做: id: {}, userId: {}", id, userId);
        return fileService.redo(id, userId);
    }


}
